/*
 * Project Porcupine
 * Copyright (C) 2012  Team Porcupine
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.towerdive.porcupine;

import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.input.InputManager;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;

/**
 *
 * @author Martin "quill18" Glaude <quill18@towerdive.com>
 */
public class MouseHandler extends AbstractControl implements ActionListener, AnalogListener {
    
    InputManager inputManager;
    Camera cam;
    Node rootNode;
    Spatial mouseCursor;

    public MouseHandler(InputManager inputManager, Camera cam, Node rootNode) {
        this.inputManager = inputManager;
        this.cam = cam;
        this.rootNode = rootNode;        
    }    

    public void onAction(String name, boolean isPressed, float tpf) {
        if (name.equals("clickPrimary")) {
            onClickPrimary();
        }
    }

    public void onAnalog(String name, float value, float tpf) {
        if (name.equals("mouseMovement")) {
            onMoveMovement();
        }
    }
        
    private void onClickPrimary() {
        // Reset results list.
        CollisionResults results = new CollisionResults();
        // Convert screen click to 3d position
        Vector2f click2d = inputManager.getCursorPosition();
        Vector3f click3d = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
        Vector3f dir = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d);
        // Aim the ray from the clicked spot forwards.
        Ray ray = new Ray(click3d, dir);
        // Collect intersections between ray and all nodes in results list.
        rootNode.collideWith(ray, results);
        // (Print the results so we see what is going on:)
        for (int i = 0; i < results.size(); i++) {
            // (For each “hit”, we know distance, impact point, geometry.)
            float dist = results.getCollision(i).getDistance();
            Vector3f pt = results.getCollision(i).getContactPoint();
            String target = results.getCollision(i).getGeometry().getName();
            System.out.println("Selection #" + i + ": " + target + " at " + pt + ", " + dist + " WU away.");
        }
        // Use the results -- we rotate the selected geometry.
        if (results.size() > 0) {
            // The closest result is the target that the player picked:
            Geometry target = results.getClosestCollision().getGeometry();
            // Here comes the action:
            if (target.getName().equals("Red Box")) {
            }
        }

    }
    
    private void onMoveMovement() {
        System.out.println("onMoveMovement()");
        mouseCursor.setLocalTranslation(getMouseContactPoint());
    }
    
    private Vector3f getMouseContactPoint() {
        // Reset results list.
        CollisionResults results = new CollisionResults();
        // Convert screen click to 3d position
        Vector2f click2d = inputManager.getCursorPosition();
        Vector3f click3d = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
        Vector3f dir = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d);
        // Aim the ray from the clicked spot forwards.
        Ray ray = new Ray(click3d, dir);
        // Collect intersections between ray and all nodes in results list.
        spatial.collideWith(ray, results);

        for(int i=0; i < results.size(); i++) {
            CollisionResult collision = results.getCollision(i);
            
            return results.getCollision(i).getContactPoint();
        }
        
        return Vector3f.ZERO;     
    }

    private void create3dMouseCursor() {
        mouseCursor = Main.app.getAssetManager().loadModel("Models/cursor_normal.j3o");
        mouseCursor.setName("mouseCursor");
        rootNode.attachChild(mouseCursor);
//        s.setCullHint(Spatial.CullHint.Always);
    }
    
    @Override
    public void setSpatial(Spatial s) {
        spatial = s;
        create3dMouseCursor();
    }

    @Override
    protected void controlUpdate(float tpf) {
        mouseCursor.setLocalTranslation(getMouseContactPoint());
    }

    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {
    }

    public Control cloneForSpatial(Spatial spatial) {
        MouseHandler control = new MouseHandler(inputManager, cam, rootNode);
        control.setSpatial(spatial);
        return control;
    }

}
